/**
 * Echarts饼图
 * @author 木人心
 * @version 1.1.0
 */
import { EChartsOption, EChartsType, PieSeriesOption } from 'echarts'
import StyleConfig from '@utils/echarts/config'
import { ChartColor } from '@utils/echarts/type'
import { ObjectUtil } from '@utils/object-util'

const styleConfig = new StyleConfig()

function getPieStyleBase (): EChartsOption {
  return {
    legend: {
      textStyle: {
        color: styleConfig.legendTextColor
      }
    },
    series: [{
      type: 'pie',
      label: { show: false, color: styleConfig.labelColor },
      avoidLabelOverlap: true
    }]
  }
}

function getPieStyle (config: {
  name: string,
  color?: ChartColor[],
  unit?: string,
  radius?: [string, string],
  center?: [string, string]
}) {
  const pieStyle = new PieStyle(config)
  pieStyle.addUnitTooltip()
  config.radius && pieStyle.setRadius(config.radius)
  config.center && pieStyle.setCenter(config.center)
  config.color && pieStyle.setColor(config.color)
  return pieStyle
}

type PieStyleConfigType = {
  name: string,
  unit: string
}

class PieStyle {
  currentOption: EChartsOption = getPieStyleBase()
  config: PieStyleConfigType = { name: '', unit: '' }

  constructor (config: {
    name: string,
    unit?: string
  }) {
    this.currentOption.series[0].name = config.name
    Object.assign(this.config, config)
    this.currentOption.globals = config
  }

  /**
   * 设置提示框
   * @param tooltip
   */
  setTooltip (tooltip: EChartsOption['tooltip'] | EChartsOption['tooltip'][]) {
    ObjectUtil.assignDeep(this.currentOption.tooltip, tooltip)
    return this
  }

  /**
   * 设置颜色
   * @param color
   */
  setColor (color: ChartColor[]) {
    this.currentOption.color = color
    return this
  }

  /**
   * 设置内外圆心大小
   * @param radius
   */
  setRadius (radius: [string, string]) {
    this.currentOption.series[0].radius = radius
    return this
  }

  /**
   * 设置圆心位置
   * @param center
   */
  setCenter (center: [string, string]) {
    this.currentOption.series[0].center = center
    return this
  }

  /**
   * 设置图例
   * @param legend
   */
  setLegend (legend: EChartsOption['legend']) {
    Object.assign(this.currentOption.legend, legend)
    return this
  }

  /**
   * 添加含单位显示的Tooltip
   */
  addUnitTooltip () {
    this.currentOption.tooltip = {
      trigger: 'item',
      formatter: (params: any) => {
        return params.seriesName + '<br/>' + params.marker + params.name + '：' + params.value + this.config.unit
      }
    }
    return this
  }

  /**
   * 添加Formatter的Label，用于圆环内显示数据
   * @param config
   */
  addValueLabel (config: { formatter?: string, rich?: PieSeriesOption['label']['rich']} = {}) {
    if (!config.formatter) {
      config.formatter = ['{value|$0}', '{unit|' + this.config.unit + '}', '{title|' + this.config.name + '}'].join('\n')
    }
    this.currentOption.series[0].label = {
      position: 'center',
      ...config
    }
    return this
  }

  /**
   * 设置Label
   * @param label
   */
  setLabel (label: PieSeriesOption['label']) {
    this.currentOption.series[0].label = Object.assign(this.currentOption.series[0].label || {}, label)
    return this
  }

  /**
   * 自定义Series的其他配置
   * @param series
   */
  setSeries (series: PieSeriesOption) {
    Object.assign(this.currentOption.series[0], series)
    return this
  }

  /**
   * 获取结果
   */
  getResult () {
    return this.currentOption
  }
}

/**
 * 饼图Util包
 */
/**
 * 饼图Util包
 */
class PieStyleUtil {
  /**
   * 添加updateValueLabel函数，添加后chart可用使用updateLabel来更新formatter中$x的值
   * updateValueLabel(...args: any[])
   * @param chart
   */
  static addUpdateValueLabel (chart: EChartsType) {
    const option = chart.getOption()
    const FORMATTER = option.series[0].label.formatter
    chart.updateValueLabel = (...args) => {
      let formatter = FORMATTER
      for (let i = 0; i < args.length; i++) {
        formatter = formatter.replace('$' + i, args[i])
      }
      chart.setOption({
        series: [{ label: { formatter } }]
      })
    }
  }

  /**
   * 添加updateValueLegend函数，添加后chart可用使用updateValueLegend来更新图例里的数据
   * updateValueLegend(data?: PieSeriesOption['data']): number
   * [推荐]如果传入data则按照data的值处理，data的值也会添加到series中。
   * 如果没有传入data，则会获取series的值并处理
   * 函数返回所有图例数据之和，方便updateValueLabel使用
   * @param chart
   * @param formatter
   */
  static addValueLegend (chart: EChartsType, formatter?: { (arg: {
      name: string, value: number, unit: string, proportion: number
    }): string }) {
    chart.updateValueLegend = (data?: PieSeriesOption['data']) => {
      let _data = data
      const config = chart.getOption().globals as PieStyleConfigType
      if (!_data) _data = chart.getOption().series[0].data || []
      let sum = 0
      const dataDic = _data.reduce((ret, item) => {
        sum += (item as any).value
        ret[(item as any).name] = (item as any).value
        return ret
      }, {})
      const option: EChartsOption = {
        legend: {
          formatter: (name) => {
            const value = dataDic[name]
            if (formatter) {
              return formatter({
                name,
                value,
                unit: config.unit,
                proportion: value / sum
              })
            } else {
              return `${name}：${value}${config.unit}`
            }
          }
        }
      }
      if (data) {
        option.series = [{ data }]
      }
      chart.setOption(option)
      return sum
    }
  }
}

export { PieStyleUtil, getPieStyle }
